using CoreManager.Repository.DbContext;
using CoreManager.Models.Entities;
using Microsoft.EntityFrameworkCore;
using System.Linq.Expressions;

namespace CoreManager.Repository.Repositories
{
    /// <summary>
    /// 通用仓储实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Repository<T> : IRepository<T> where T : BaseEntity, new()
    {
        protected readonly CoreManagerDbContext _context;
        private readonly DbSet<T> _dbSet;

        public Repository(CoreManagerDbContext context)
        {
            _context = context;
            _dbSet = context.Set<T>();
        }

        public CoreManagerDbContext Context => _context;

        public async Task<T?> GetByIdAsync(int id)
        {
            return await _dbSet.FindAsync(id);
        }

        public async Task<T?> GetAsync(Expression<Func<T, bool>> expression)
        {
            return await _dbSet.FirstOrDefaultAsync(expression);
        }

        public async Task<List<T>> GetAllAsync()
        {
            return await _dbSet.ToListAsync();
        }

        public async Task<List<T>> GetListAsync(Expression<Func<T, bool>> expression)
        {
            return await _dbSet.Where(expression).ToListAsync();
        }

        public async Task<(List<T> Items, int Total)> GetPagedListAsync(
            Expression<Func<T, bool>>? expression = null,
            int pageIndex = 1,
            int pageSize = 20,
            Expression<Func<T, object>>? orderBy = null,
            bool isAsc = true)
        {
            var query = _dbSet.AsQueryable();

            if (expression != null)
            {
                query = query.Where(expression);
            }

            var total = await query.CountAsync();

            if (orderBy != null)
            {
                query = isAsc ? query.OrderBy(orderBy) : query.OrderByDescending(orderBy);
            }
            else
            {
                query = query.OrderBy(x => x.Id);
            }

            var items = await query.Skip((pageIndex - 1) * pageSize)
                                   .Take(pageSize)
                                   .ToListAsync();
            
            return (items, total);
        }

        public async Task<int> InsertAsync(T entity)
        {
            entity.CreateTime = DateTime.Now;
            await _dbSet.AddAsync(entity);
            await _context.SaveChangesAsync();
            return entity.Id;
        }

        public async Task<int> InsertRangeAsync(List<T> entities)
        {
            foreach (var entity in entities)
            {
                entity.CreateTime = DateTime.Now;
            }
            await _dbSet.AddRangeAsync(entities);
            return await _context.SaveChangesAsync();
        }

        public async Task<bool> UpdateAsync(T entity)
        {
            entity.UpdateTime = DateTime.Now;
            _dbSet.Update(entity);
            var result = await _context.SaveChangesAsync();
            return result > 0;
        }

        public async Task<bool> UpdateAsync(Expression<Func<T, bool>> expression, Expression<Func<T, T>> updateExpression)
        {
            // 注意：EF Core的ExecuteUpdateAsync需要不同的表达式格式
            // 这里提供一个基础实现，具体的批量更新可能需要在具体的Repository中实现
            var entities = await _dbSet.Where(expression).ToListAsync();
            foreach (var entity in entities)
            {
                // 应用更新表达式
                var compiled = updateExpression.Compile();
                var updatedEntity = compiled(entity);
                
                // 更新实体属性
                _context.Entry(entity).CurrentValues.SetValues(updatedEntity);
                entity.UpdateTime = DateTime.Now;
            }
            
            var result = await _context.SaveChangesAsync();
            return result > 0;
        }

        public async Task<bool> DeleteAsync(int id)
        {
            var entity = await _dbSet.FindAsync(id);
            if (entity != null)
            {
                _dbSet.Remove(entity);
                var result = await _context.SaveChangesAsync();
                return result > 0;
            }
            return false;
        }

        public async Task<bool> DeleteAsync(Expression<Func<T, bool>> expression)
        {
            var result = await _dbSet.Where(expression).ExecuteDeleteAsync();
            return result > 0;
        }

        public async Task<bool> SoftDeleteAsync(int id)
        {
            var result = await _dbSet.Where(x => x.Id == id)
                .ExecuteUpdateAsync(x => x.SetProperty(p => p.IsDeleted, true)
                                         .SetProperty(p => p.UpdateTime, DateTime.Now));
            return result > 0;
        }

        public async Task<bool> ExistsAsync(Expression<Func<T, bool>> expression)
        {
            return await _dbSet.AnyAsync(expression);
        }

        public async Task<int> CountAsync(Expression<Func<T, bool>>? expression = null)
        {
            var query = _dbSet.AsQueryable();
            if (expression != null)
            {
                query = query.Where(expression);
            }
            return await query.CountAsync();
        }

        public IQueryable<T> GetQueryable()
        {
            return _dbSet.AsQueryable();
        }
    }
}